﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;

namespace VSClean
{
    class Program
    {
        const string MSBuildPath = @"C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe";

        static void Main(string[] args)
        {
            if (args == null || args.Length == 0 || !Directory.Exists(args[0]))
            {
                Console.WriteLine("Please Supply a valid path");
            }

            string startDir = args[0];
            List<ManualResetEvent> waitHandles = new List<ManualResetEvent>();

            ProcessDirectory(startDir, waitHandles);

            foreach (WaitHandle wh in waitHandles)
            {
                wh.WaitOne();
            }

            Console.WriteLine("Done");
        }

        private static void ProcessDirectory(string startDir, List<ManualResetEvent> waitHandles)
        {
            ProcessSolutions(startDir, waitHandles);

            if (Path.GetFileNameWithoutExtension(startDir) == "TestResults")
            {
                try
                {
                    Directory.Delete(startDir, true);
                }
                catch (UnauthorizedAccessException ex)
                {
                    WriteError(ex);
                }
                catch (IOException ex)
                {
                    WriteError(ex);
                }
            }

            var subDirectories = Directory.GetDirectories(startDir);

            subDirectories.ToList().ForEach(s => ProcessDirectory(s, waitHandles));
        }

        private static void WriteError(Exception ex)
        {
            var currentColor = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(ex.Message);
            Console.ForegroundColor = currentColor;
        }

        private static void ProcessSolutions(string startDir, List<ManualResetEvent> waitHandles)
        {
            string[] solutionFiles = Directory.GetFiles(startDir, "*.sln");
            if (solutionFiles != null && solutionFiles.Length > 0)
            {
                foreach (string solution in solutionFiles)
                {
                    var signal = new ManualResetEvent(false);
                    waitHandles.Add(signal);
                    ThreadPool.QueueUserWorkItem(o =>
                    {
                        Console.WriteLine("building: " + solution);

                        try
                        {
                            var build = Process.Start(new ProcessStartInfo(MSBuildPath) 
                                { 
                                    Arguments = string.Format("\"{0}\" /m /t:clean", solution)
                                });

                            build.WaitForExit();
                            Console.WriteLine("Success: " + solution);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("failed:\n\t{0}\n\tError:{1}", solution, ex.Message);
                        }
                        finally
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            signal.Set();
                        }
                    });
                }
            }
        }
    }
}
